﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Input;

namespace SampleCode.VirtualFS.ViewModel
{
    /// <summary>
    /// A base ViewModel class
    /// </summary>
    public abstract class FsViewModelBase : INotifyPropertyChanged, IDisposable
    {
        /// <summary>
        /// Allows/disallows editing the entity
        /// </summary>
        protected bool IsReadOnly;

        /// <summary>
        /// Object name
        /// </summary>
        public virtual string Name { get; set; }

        /// <summary>
        /// INotifyPropertyChanged implementation
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Edit component visibility - visible when in edit mode
        /// </summary>
        public Visibility EditBoxVisible
        {
            get { return InEditMode ? Visibility.Visible : Visibility.Collapsed; }
            set { InEditMode = (value == Visibility.Visible); }
        }

        /// <summary>
        /// View component visibility - visible when not in edit mode
        /// </summary>
        public Visibility ViewBoxVisible
        {
            get { return InEditMode ? Visibility.Collapsed : Visibility.Visible; }
            set { InEditMode = (value == Visibility.Collapsed); }
        }

        private bool _inEditMode;
        /// <summary>
        /// Are we in edit mode?
        /// </summary>
        protected bool InEditMode
        {
            get { return _inEditMode; }
            set
            {
                _inEditMode = value;
                OnPropertyChanged("ViewBoxVisible");
                OnPropertyChanged("EditBoxVisible");
            }
        }

        private FsRelayCommand _editCommand;
        /// <summary>
        /// Start editing command
        /// </summary>
        public ICommand EditCommand
        {
            get
            {
                return _editCommand ?? (_editCommand = new FsRelayCommand
                (_ =>
                    {
                        InEditMode = true;
                    },
                _ => !IsReadOnly
                ));
            }
        }

        private FsRelayCommand _saveChangesCommand;
        /// <summary>
        /// Stop editing command
        /// </summary>
        public ICommand SaveChangesCommand
        {
            get
            {
                return _saveChangesCommand ?? (_saveChangesCommand = new FsRelayCommand
                (_ =>
                    {
                        InEditMode = false;
                    },
                _ => !IsReadOnly
                ));
            }
        }

        /// <summary>
        /// Raises this object's PropertyChanged event.
        /// </summary>
        /// <param name="propertyName">The property that has a new value.</param>
        protected virtual void OnPropertyChanged(string propertyName)
        {
            // for not to be afraid of multi-threading
            var handler = PropertyChanged;
            if (handler == null) return;

            handler(this, new PropertyChangedEventArgs(propertyName));
        }

        /// <summary>
        /// Invoked when this object is being removed from the application
        /// and will be subject to garbage collection.
        /// </summary>
        public void Dispose()
        {
            OnDispose();
        }

        /// <summary>
        /// Child classes can override this method to perform 
        /// clean-up logic, such as removing event handlers.
        /// </summary>
        protected virtual void OnDispose()
        {
        }

#if DEBUG
        /// <summary>
        /// Useful for ensuring that ViewModel objects are properly garbage collected.
        /// </summary>
        ~FsViewModelBase()
        {
            Debug.WriteLine( string.Format("{0} ({1}) ({2}) Finalized", GetType().Name, Name, GetHashCode()) );
        }
#endif

    }
}
